﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using FileManager_Client.BusinessLogic.FileManagerUserService;
using FileManager_Client.Utility;

namespace FileManager_Client.BusinessLogic
{
    public class FileService
    {
        #region File Hash Code

        public static string Md5File(string fileName)
        {
            return HashFile(fileName, "md5");
        }

        private static string ByteArrayToHexString(ICollection<byte> bytes)
        {
            var length = bytes.Count;
            var builder = new StringBuilder();
            foreach (var num in bytes)
            {
                builder.Append(Convert.ToString(Convert.ToInt32(num), 0x10));
            }
            return builder.ToString();
        }

        private static byte[] HashData(Stream stream, string algName)
        {
            HashAlgorithm algorithm;
            if (algName == null)
            {
                throw new ArgumentNullException("algName 不能为 null");
            }
            if (String.Compare(algName, "sha1", StringComparison.OrdinalIgnoreCase) == 0)
            {
                algorithm = SHA1.Create();
            }
            else
            {
                if (String.Compare(algName, "md5", StringComparison.OrdinalIgnoreCase) != 0)
                {
                    throw new Exception("algName 只能使用 sha1 或 md5");
                }
                algorithm = MD5.Create();
            }
            return algorithm.ComputeHash(stream);
        }

        private static string HashFile(string fileName, string algName)
        {
            if (!File.Exists(fileName))
            {
                return string.Empty;
            }
            var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            var bytes = HashData(stream, algName);
            stream.Close();
            return ByteArrayToHexString(bytes);
        }

        public static string Md5File(FileStream fs)
        {
            return ByteArrayToHexString(HashData(fs, "md5"));
        }

        //调用windows API获取磁盘空闲空间
        //导入库
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern bool GetDiskFreeSpace([MarshalAs(UnmanagedType.LPTStr)] string rootPathName,
                                                    ref int sectorsPerCluster, ref int bytesPerSector,
                                                    ref int numberOfFreeClusters, ref int totalNumbeOfClusters);

        /// <summary>
        /// 获取指定路径的大小
        /// </summary>
        /// <param name="dirPath">路径</param>
        /// <returns></returns>
        public static long GetDirectoryLength(string dirPath)
        {
            long len = 0;
            //判断该路径是否存在（是否为文件夹）
            if (!Directory.Exists(dirPath))
            {
                //查询文件的大小
                len = FileSize(dirPath);
            }
            else
            {
                //定义一个DirectoryInfo对象
                DirectoryInfo di = new DirectoryInfo(dirPath);

                //通过GetFiles方法，获取di目录中的所有文件的大小
                foreach (FileInfo fi in di.GetFiles())
                {
                    len += fi.Length;
                }
                //获取di中所有的文件夹，并存到一个新的对象数组中，以进行递归
                DirectoryInfo[] dis = di.GetDirectories();
                if (dis.Length > 0)
                {
                    for (int i = 0; i < dis.Length; i++)
                    {
                        len += GetDirectoryLength(dis[i].FullName);
                    }
                }
            }
            return len;
        }

        /// <summary>
        /// 获取指定路径的占用空间
        /// </summary>
        /// <param name="dirPath">路径</param>
        /// <returns></returns>
        public static long GetDirectorySpace(string dirPath)
        {
            //返回值
            long len = 0;
            //判断该路径是否存在（是否为文件夹）
            if (!Directory.Exists(dirPath))
            {
                //如果是文件，则调用
                len = FileSpace(dirPath);
            }
            else
            {
                //定义一个DirectoryInfo对象
                DirectoryInfo di = new DirectoryInfo(dirPath);
                //本机的簇值
                long clusterSize = GetClusterSize(di);
                //遍历目录下的文件，获取总占用空间
                foreach (FileInfo fi in di.GetFiles())
                {
                    //文件大小除以簇，余若不为0
                    if (fi.Length%clusterSize != 0)
                    {
                        decimal res = fi.Length/clusterSize;
                        //文件大小除以簇，取整数加1。为该文件占用簇的值
                        int clu = Convert.ToInt32(Math.Ceiling(res)) + 1;
                        long result = clusterSize*clu;
                        len += result;
                    }
                    else
                    {
                        //余若为0，则占用空间等于文件大小
                        len += fi.Length;
                    }
                }
                //获取di中所有的文件夹，并存到一个新的对象数组中，以进行递归
                DirectoryInfo[] dis = di.GetDirectories();
                if (dis.Length > 0)
                {
                    for (int i = 0; i < dis.Length; i++)
                    {
                        len += GetDirectorySpace(dis[i].FullName);
                    }
                }
            }
            return len;
        }

        //所给路径中所对应的文件大小
        public static long FileSize(string filePath)
        {
            //定义一个FileInfo对象，是指与filePath所指向的文件相关联，以获取其大小
            FileInfo fileInfo = new FileInfo(filePath);
            return fileInfo.Length;
        }

        //所给路径中所对应的文件占用空间
        public static long FileSpace(string filePath)
        {
            long temp = 0;
            //定义一个FileInfo对象，是指与filePath所指向的文件相关联，以获取其大小
            FileInfo fileInfo = new FileInfo(filePath);
            long clusterSize = GetClusterSize(fileInfo);
            if (fileInfo.Length%clusterSize != 0)
            {
                decimal res = fileInfo.Length/clusterSize;
                int clu = Convert.ToInt32(Math.Ceiling(res)) + 1;
                temp = clusterSize*clu;
            }
            else
            {
                return fileInfo.Length;
            }
            return temp;
        }

        public static DiskInfo GetDiskInfo(string rootPathName)
        {
            DiskInfo diskInfo = new DiskInfo();
            int sectorsPerCluster = 0, bytesPerSector = 0, numberOfFreeClusters = 0, totalNumberOfClusters = 0;
            GetDiskFreeSpace(rootPathName, ref sectorsPerCluster, ref bytesPerSector, ref numberOfFreeClusters,
                             ref totalNumberOfClusters);

            //每簇的扇区数
            diskInfo.SectorsPerCluster = sectorsPerCluster;
            //每扇区字节
            diskInfo.BytesPerSector = bytesPerSector;

            return diskInfo;
        }

        //// <summary>
        /// 结构。硬盘信息
        /// </summary>
        public struct DiskInfo
        {
            public string RootPathName;
            //每簇的扇区数
            public int SectorsPerCluster;
            //每扇区字节
            public int BytesPerSector;
            public int NumberOfFreeClusters;
            public int TotalNumberOfClusters;
        }

        /// <summary>
        /// 获取每簇的字节
        /// </summary>
        /// <param name="file">指定文件</param>
        /// <returns></returns>
        public static long GetClusterSize(FileInfo file)
        {
            long clusterSize = 0;
            DiskInfo diskInfo = new DiskInfo();
            diskInfo = GetDiskInfo(file.Directory.Root.FullName);
            clusterSize = (diskInfo.BytesPerSector*diskInfo.SectorsPerCluster);
            return clusterSize;
        }

        /// <summary>
        /// 获取每簇的字节
        /// </summary>
        /// <param name="dir">指定目录</param>
        /// <returns></returns>
        public static long GetClusterSize(DirectoryInfo dir)
        {
            long clusterSize = 0;
            DiskInfo diskInfo = new DiskInfo();
            diskInfo = GetDiskInfo(dir.Root.FullName);
            clusterSize = (diskInfo.BytesPerSector*diskInfo.SectorsPerCluster);
            return clusterSize;
        }

        #endregion

        #region File Service

        public FileResultCollection GetFolderFileCollection(FileQueryArgs fileQueryArgs)
        {
            var result = new FileResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.GetFolderFileCollection(fileQueryArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetFolderFileCollection has problem", ex);
            }
            return result;
        }

        public FileDeleteResult DeleteFile(FileDeleteArgs fileDeleteArgs)
        {
            var result = new FileDeleteResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.DeleteFileService(fileDeleteArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DeleteFile has problem", ex);
            }
            return result;
        }

        public FileReNameResult ChangeFileName(FileReNameArgs fileReNameArgs)
        {
            var result = new FileReNameResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.ChangeFileNameService(fileReNameArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("ChangeFileName has problem", ex);
            }
            return result;
        }

        public FolderReNameResult ChangeFolderName(FolderReNameArgs folderReNameArgs)
        {
            var result = new FolderReNameResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.ChangeFolderNameService(folderReNameArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("ChangeFolderName has problem", ex);
            }
            return result;
        }

        public FolderDeleteResult DeleteFolder(FolderDeleteArgs folderDeleteArgs)
        {
            var result = new FolderDeleteResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.DeleteFolderService(folderDeleteArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DeleteFolder has problem", ex);
            }
            return result;
        }

        public FileCopyToResult CopyFileTo(FileCopyToArgs fileCopyToArgs)
        {
            var result = new FileCopyToResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CopyFileToOtherFolder(fileCopyToArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CopyFileTo has problem", ex);
            }
            return result;
        }

        public FileCutToResult CutFileTo(FileCutToArgs fileCutToArgs)
        {
            var result = new FileCutToResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CutFileToOtherFolder(fileCutToArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CutFileTo has problem", ex);
            }
            return result;
        }

        public FolderCopyToResult CopyFolderTo(FolderCopyToArgs folderCopyToArgs)
        {
            var result = new FolderCopyToResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CopyFolderToOtherFolder(folderCopyToArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CopyFolderTo has problem", ex);
            }
            return result;
        }

        public FolderCutToResult CutFolderTo(FolderCutToArgs folderCutToArgs)
        {
            var result = new FolderCutToResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CutFolderToOtherFolder(folderCutToArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CutFolderTo has problem", ex);
            }
            return result;
        }

        public NewFolderResult CreateFolder(NewFolderArgs newFolderArgs)
        {
            var result = new NewFolderResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CreateNewFolder(newFolderArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CreateFolder has problem", ex);
            }
            return result;
        }

        public FileRoleAddResultCollection GetFoleRoleCollection(FileRoleAddArgs fileRoleAddArgs)
        {
            var result = new FileRoleAddResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.GetFolderRole(fileRoleAddArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetFoleRoleCollection has problem", ex);
            }
            return result;
        }

        public NewFileRoleResultCollection CreateNewFileRole(NewFileRoleCollectionArgs newFileRoleCollectionArgs)
        {
            var result = new NewFileRoleResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.NewFileRole(newFileRoleCollectionArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("CreateNewFileRole has problem", ex);
            }
            return result;
        }

        public FileRoleChangeResult ChangeFileRole(FileRoleChangeArgs fileRoleChangeArgs)
        {
            var result = new FileRoleChangeResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.ChangeFileRole(fileRoleChangeArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("ChangeFileRole has problem", ex);
            }
            return result;
        }

        public ApplySubFolderRoleResult ApplySubFolderRole(ApplySubFolderRoleArgs applySubFolderRoleArgs)
        {
            var result = new ApplySubFolderRoleResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.ApplySubFolderRole(applySubFolderRoleArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("ApplySubFolderRole has problem", ex);
            }
            return result;
        }

        public DeleteFileRoleResult DeleteFileRole(DeleteFileRoleArgs deleteFileRoleArgs)
        {
            var result = new DeleteFileRoleResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.DeleteFileRole(deleteFileRoleArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DeleteFileRole has problem", ex);
            }
            return result;
        }

        public FileLogQueryCountResult GetFileLogCount(FileLogQueryArgs fileLogQueryArgs)
        {
            var result = new FileLogQueryCountResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.GetFileLogCount(fileLogQueryArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetFileLogCount has problem", ex);
            }
            return result;
        }

        public FileLogResultCollection GetFileLog(FilelogQueryPageArgs filelogQueryPageArgs)
        {
            var result = new FileLogResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.GetFileLog(filelogQueryPageArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetFileLog has problem", ex);
            }
            return result;
        }

        public FileResultCollection SearchFile(FileSearchArgs fileSearchArgs)
        {
            var result = new FileResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.SearchFile(fileSearchArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("SearchFile has problem", ex);
            }
            return result;
        }

        public CheckFileResult CheckFile(CheckFileUploadingArgs checkFileUploadingArgs)
        {
            var result = new CheckFileResult();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CheckFile(checkFileUploadingArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("SearchFile has problem", ex);
            }
            return result;
        }

        public void DeleteUploadingFile(string fileServerPath)
        {
            try
            {
                var args = new DeleteUploadingFileArgs {FileServerPathk__BackingField = fileServerPath};
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    wcfService.DeleteUploadingFile(args);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DeleteUploadingFile has problem", ex);
            }
        }

        public DownloadingCheckFileResultCollection DownloadingCheckFile(
            DownlaodingCheckFilesArgs downlaodingCheckFilesArgs)
        {
            var result = new DownloadingCheckFileResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.CheckFileInfomation(downlaodingCheckFilesArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DownloadingCheckFile has problem", ex);

            }
            return result;
        }

        public void DownloadingFileSuccess(DownloadingSuccessArgs downloadingSuccessArgs)
        {
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    wcfService.DownloadingFileSuccess(downloadingSuccessArgs);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("DownloadingFileSuccess has problem", ex);

            }
        }

        public DepartmentSizeResultCollection GetDepartmentSizeCollection()
        {
            var result = new DepartmentSizeResultCollection();
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    result = wcfService.GetDepartmentSizeCollection();
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetDepartmentSize has problem", ex);
            }
            return result;
        }

        public int GetDepartmentSize(string departmentId)
        {
            var size = 0;
            try
            {
                var wcfService =
                    CacheGlobal.GetCache(GlobalString.System_Config_String.Wcf_FileServiceCacheKey) as
                    FileManager_UserServiceClient;
                if (wcfService != null)
                    size = wcfService.GetDepartmentSizeMB(departmentId);
            }
            catch (Exception ex)
            {
                LogLoader.Instance.Log.Error("GetDepartmentSize has problem", ex);
            }
            return size;
        }
        #endregion
    }
}